package com.compass.mobile.ui.activity

import CompassAppHelper
import LogUtil
import UserInfoManager
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.Rect
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.MediaPlayer
import android.os.Build
import android.os.Bundle
import android.widget.ImageView
import androidx.activity.viewModels
import com.compass.mobile.R
import com.compass.mobile.databinding.ActivityVideoCallBinding
import com.compass.mobile.framework.base.BaseVBActivity
import com.compass.mobile.framework.constant.CANCEL_INVITE
import com.compass.mobile.framework.constant.CLOSE_EVENT
import com.compass.mobile.framework.constant.NIM_APP_KEY
import com.compass.mobile.framework.ext.gone
import com.compass.mobile.framework.ext.onClick
import com.compass.mobile.framework.ext.visible
import com.compass.mobile.framework.utils.FocusViewUtils
import com.compass.mobile.framework.utils.LiveDataBus
import com.compass.mobile.ui.dialog.CommonMessageDialog
import com.compass.mobile.ui.viewModel.DoctorViewModel
import com.compass.mobile.ui.viewModel.VideoCallViewModel
import com.netease.lava.nertc.sdk.LastmileProbeResult
import com.netease.lava.nertc.sdk.NERtc
import com.netease.lava.nertc.sdk.NERtcCallback
import com.netease.lava.nertc.sdk.NERtcCallbackEx
import com.netease.lava.nertc.sdk.NERtcConstants
import com.netease.lava.nertc.sdk.NERtcEx
import com.netease.lava.nertc.sdk.NERtcUserJoinExtraInfo
import com.netease.lava.nertc.sdk.NERtcUserLeaveExtraInfo
import com.netease.lava.nertc.sdk.audio.NERtcAudioStreamType
import com.netease.lava.nertc.sdk.stats.NERtcAudioVolumeInfo
import com.netease.lava.nertc.sdk.video.NERtcEncodeConfig
import com.netease.lava.nertc.sdk.video.NERtcRemoteVideoStreamType
import com.netease.lava.nertc.sdk.video.NERtcVideoConfig
import com.netease.lava.nertc.sdk.video.NERtcVideoStreamType
import com.netease.nimlib.sdk.avsignalling.event.InvitedEvent
import com.netease.nimlib.sdk.avsignalling.model.ChannelBaseInfo
import getStringFromResource
import setBlurView
import setUrlCircle
import toJson
import java.nio.ByteBuffer


/**
 * Description： 视频被叫测试
 * Date:2024/6/13 14:21
 */
class VideoAnswerActivity : BaseVBActivity<ActivityVideoCallBinding>() {

    companion object {
        fun start(context: Context, invitedEvent: InvitedEvent) {
            val intent = Intent(context, VideoAnswerActivity::class.java)
            intent.putExtra("invitedEvent", invitedEvent)
            context.startActivity(intent)
        }
    }


    private lateinit var inviteEvent: InvitedEvent
    private val videoCallViewModel: VideoCallViewModel by viewModels()
    private val doctorViewModel :DoctorViewModel by viewModels()

    private var neRtcCallback: NERtcCallback = object : NERtcCallbackEx {
        override fun onUserSubStreamVideoStart(uid: Long, maxProfile: Int) {}
        override fun onUserSubStreamVideoStop(uid: Long) {}
        override fun onUserAudioMute(uid: Long, muted: Boolean) {}
        override fun onUserVideoMute(uid: Long, muted: Boolean) {}
        override fun onUserVideoMute(
            streamType: NERtcVideoStreamType,
            uid: Long,
            muted: Boolean
        ) {
        }

        override fun onFirstAudioDataReceived(uid: Long) {}
        override fun onLocalAudioFirstPacketSent(audioStreamType: NERtcAudioStreamType) {}
        override fun onFirstVideoDataReceived(uid: Long) {}
        override fun onFirstVideoDataReceived(streamType: NERtcVideoStreamType, uid: Long) {}
        override fun onFirstAudioFrameDecoded(userID: Long) {}
        override fun onFirstVideoFrameDecoded(userID: Long, width: Int, height: Int) {}
        override fun onFirstVideoFrameRender(
            userID: Long,
            streamType: NERtcVideoStreamType,
            width: Int,
            height: Int,
            elapsedTime: Long
        ) {
        }

        override fun onFirstVideoFrameDecoded(
            streamType: NERtcVideoStreamType,
            userID: Long,
            width: Int,
            height: Int
        ) {
        }

        override fun onUserVideoProfileUpdate(uid: Long, maxProfile: Int) {}
        override fun onAudioDeviceChanged(selected: Int) {}
        override fun onAudioDeviceStateChange(deviceType: Int, deviceState: Int) {}
        override fun onVideoDeviceStageChange(deviceState: Int) {}
        override fun onConnectionTypeChanged(newConnectionType: Int) {}
        override fun onReconnectingStart() {}
        override fun onReJoinChannel(result: Int, channelId: Long) {}
        override fun onAudioMixingStateChanged(reason: Int) {}
        override fun onAudioMixingTimestampUpdate(timestampMs: Long) {}
        override fun onAudioEffectTimestampUpdate(id: Long, timestampMs: Long) {}
        override fun onAudioEffectFinished(effectId: Int) {}
        override fun onLocalAudioVolumeIndication(volume: Int) {}
        override fun onLocalAudioVolumeIndication(volume: Int, vadFlag: Boolean) {}
        override fun onRemoteAudioVolumeIndication(
            volumeArray: Array<NERtcAudioVolumeInfo>,
            totalVolume: Int
        ) {
        }

        override fun onLiveStreamState(taskId: String, pushUrl: String, liveState: Int) {}
        override fun onConnectionStateChanged(state: Int, reason: Int) {}
        override fun onCameraFocusChanged(rect: Rect) {}
        override fun onCameraExposureChanged(rect: Rect) {}
        override fun onRecvSEIMsg(userID: Long, seiMsg: String) {}
        override fun onAudioRecording(code: Int, filePath: String) {}
        override fun onError(code: Int) {}
        override fun onWarning(code: Int) {}
        override fun onApiCallExecuted(apiName: String, result: Int, message: String) {}
        override fun onMediaRelayStatesChange(state: Int, channelName: String) {}
        override fun onMediaRelayReceiveEvent(event: Int, code: Int, channelName: String) {}
        override fun onLocalPublishFallbackToAudioOnly(
            isFallback: Boolean,
            streamType: NERtcVideoStreamType
        ) {
        }

        override fun onRemoteSubscribeFallbackToAudioOnly(
            uid: Long,
            isFallback: Boolean,
            streamType: NERtcVideoStreamType
        ) {
        }

        override fun onLastmileQuality(quality: Int) {}
        override fun onLastmileProbeResult(result: LastmileProbeResult) {}
        override fun onMediaRightChange(
            isAudioBannedByServer: Boolean,
            isVideoBannedByServer: Boolean
        ) {
        }

        override fun onRemoteVideoSizeChanged(
            userId: Long,
            videoType: NERtcVideoStreamType,
            width: Int,
            height: Int
        ) {
        }

        override fun onLocalVideoRenderSizeChanged(
            videoType: NERtcVideoStreamType,
            width: Int,
            height: Int
        ) {
        }

        override fun onVirtualBackgroundSourceEnabled(enabled: Boolean, reason: Int) {}
        override fun onUserSubStreamAudioStart(uid: Long) {}
        override fun onUserSubStreamAudioStop(uid: Long) {}
        override fun onUserSubStreamAudioMute(uid: Long, muted: Boolean) {}
        override fun onPermissionKeyWillExpire() {}
        override fun onUpdatePermissionKey(key: String, error: Int, timeout: Int) {}
        override fun onLocalVideoWatermarkState(
            videoStreamType: NERtcVideoStreamType,
            state: Int
        ) {
        }

        override fun onUserDataStart(uid: Long) {}
        override fun onUserDataStop(uid: Long) {}
        override fun onUserDataReceiveMessage(
            uid: Long,
            bufferData: ByteBuffer,
            bufferSize: Long
        ) {
        }

        override fun onUserDataStateChanged(uid: Long) {}
        override fun onUserDataBufferedAmountChanged(uid: Long, previousAmount: Long) {}
        override fun onLabFeatureCallback(key: String, param: Any) {}

        //本端用户加入房间结果回调
        override fun onJoinChannel(result: Int, channelId: Long, elapsed: Long, uid: Long) {
            if (result == NERtcConstants.ErrorCode.OK) {
                // 加入房间成功
                mBinding.videoViewSmall.visible()
                NERtcEx.getInstance().setupLocalVideoCanvas(mBinding.videoViewSmall)
                //加入房间前提前设置好视频开启状态
                NERtcEx.getInstance()
                    .enableLocalVideo(NERtcVideoStreamType.kNERtcVideoStreamTypeMain, true)
                innerStop()
                mBinding.btnAnswerVideo.gone()
                mBinding.btnHangUp.gone()
                mBinding.llEnableAudio.visible()
                mBinding.llEnableVideo.visible()
                mBinding.llHangUp.visible()

                mBinding.llDoctorSimpleInfo.gone()
                mBinding.llDoctorInfo.visible()
                LogUtil.d("加入房间成功", tag = tag)
            } else {
                // 加入房间失败 ，退出页面
                finish()
            }
        }

        override fun onLeaveChannel(result: Int) {

        }
        override fun onUserJoined(uid: Long) {
            //设置远端画布
            NERtcEx.getInstance().setupRemoteVideoCanvas(mBinding.videoViewBig, uid)
            LogUtil.d("用户加入房间", tag = tag)
        }

        override fun onUserJoined(uid: Long, joinExtraInfo: NERtcUserJoinExtraInfo) {
        }

        override fun onUserLeave(uid: Long, reason: Int) {

            LogUtil.d("用户离开房间回调", tag = tag)
        }

        override fun onUserLeave(
            uid: Long,
            reason: Int,
            leaveExtraInfo: NERtcUserLeaveExtraInfo
        ) {
        }

        override fun onUserAudioStart(uid: Long) {
            LogUtil.d(
                "  当房间中的其他用户发布视频流时，本端会触发 onUserVideoStart 回调。",
                tag = tag
            )

        }

        override fun onUserAudioStop(uid: Long) {}
        override fun onUserVideoStart(uid: Long, maxProfile: Int) {
//            NERtcEx.getInstance().setupLocalVideoCanvas(mBinding.videoViewSmall)
            //对方开启视频，按需设置画布及订阅视频
            NERtcEx.getInstance().setupRemoteVideoCanvas(mBinding.videoViewBig, uid)
            NERtcEx.getInstance().subscribeRemoteVideoStream(
                uid,
                NERtcRemoteVideoStreamType.kNERtcRemoteVideoStreamTypeHigh,
                true
            )
        }

        override fun onUserVideoStop(uid: Long) {
            //释放之前绑定的画布
            NERtcEx.getInstance().setupRemoteVideoCanvas(null, uid)
        }

        override fun onDisconnect(reason: Int) {
            // 与服务器断连 ，退出页面
            finish()
        }

        override fun onClientRoleChange(oldRole: Int, newRole: Int) {} //*******其他一些回调******
    }


    override fun initView(savedInstanceState: Bundle?) {
        inviteEvent = intent.serializable("invitedEvent")!!
        //小画布置于大画布上面
        mBinding.videoViewSmall.setZOrderMediaOverlay(true)
        FocusViewUtils.scaleView(mBinding.btnAnswerVideo, 0)
        FocusViewUtils.scaleView(mBinding.btnHangUp, 0)
        FocusViewUtils.scaleView(mBinding.llEnableVideo, 0)
        FocusViewUtils.scaleView(mBinding.llEnableAudio, 0)
        FocusViewUtils.scaleView(mBinding.llHangUp, 0)
        if(inviteEvent.fromAccountId.isNotEmpty()){
            doctorViewModel.getDoctorInfo(inviteEvent.fromAccountId)
        }
//        mBinding.ivBg.setBlurView("",Color.argb(1,21,43,75))
//        mBinding.ivBg.applyBlurryEffect(Color.argb(1,21,43,75))
    }

    override fun initData() {
        // 初始化SDK
        try {
            NERtc.getInstance()
                .init(CompassAppHelper.getApplication(), NIM_APP_KEY, neRtcCallback, null)
        } catch (e: Exception) {
            e.printStackTrace()
            showToast("SDK初始化失败")
            finish()
            return
        }



        //指定前置摄像头
//        NERtcEx.getInstance().switchCameraWithPosition(NERtcConstants.CameraPosition.CAMERA_POSITION_FRONT)
        //指定后置摄像头
//        NERtcEx.getInstance().switchCameraWithPosition(NERtcConstants.CameraPosition.CAMERA_POSITION_BACK)

        //设置视频  通用 1 对 1 聊天场景
        NERtcEx.getInstance().setChannelProfile(NERtcConstants.RTCChannelProfile.LIVE_BROADCASTING)
        //设置音频profile为标准模式，scenario为语音场景
        NERtcEx.getInstance().setAudioProfile(
            NERtcConstants.AudioProfile.STANDARD,
            NERtcConstants.AudioScenario.SPEECH
        );
        //设置本地视频参数
        val videoConfig = NERtcVideoConfig()
        videoConfig.width = 720
        videoConfig.height = 1080
        videoConfig.frameRate = NERtcEncodeConfig.NERtcVideoFrameRate.FRAME_RATE_FPS_24
        NERtcEx.getInstance().setLocalVideoConfig(videoConfig)
        // 禁用双流模式
        NERtcEx.getInstance().enableDualStreamMode(false)
        //设置本地画布
        NERtcEx.getInstance().setupLocalVideoCanvas(mBinding.videoViewSmall)
        NERtcEx.getInstance().startVideoPreview(NERtcVideoStreamType.kNERtcVideoStreamTypeMain)
        mBinding.btnAnswerVideo.requestFocus()
        innerPlay(this)
        LiveDataBus.get().with(CLOSE_EVENT, ChannelBaseInfo::class.java).observe(this) {
            //离开频道
            videoCallViewModel.leave(it)
            leaveAndClose()
        }

        LiveDataBus.get().with(CANCEL_INVITE, ChannelBaseInfo::class.java).observe(this) {
            //离开频道
            leaveAndClose()
        }

        videoCallViewModel.joinChannelLiveData.observe(this) {
            it?.let {
                //加入房间
                LogUtil.d("${it.toJson()}", tag = tag)
                var channelName = it.channelBaseInfo.channelName
                UserInfoManager.getImUserAccount()?.let { uid ->
                    //token暂时传空  等后台做好了再传
                    //加入房间
                    NERtcEx.getInstance()
                        .startVideoPreview()//加入房间时，调用 stopVideoPreview(streamType) 方法停止预览
                    NERtcEx.getInstance().joinChannel(null, channelName, uid.toLong(), null)
                }

            }
        }

        doctorViewModel.doctorInfoLiveData.observe(this){
            if(it!=null){
                mBinding.apply {
                    //初始化医生数据 未接通时医生头像
                    ivDoctorAvatar.setUrlCircle(it.avatar)
                    tvDoctorName.text = it.name
                    tvDoctorPosition.text = it.positionName


                    //左边布局医生信息
                    ivDoctorInfoAvatar.setUrlCircle(it.avatar)
                    tvDoctorInfoName.text = it.name
                    tvDoctorInfoLevel.text = it.positionName
                    //科室
                    tvDepartment.text = it.departmentName
                    //好评率
                    tvRate.text = it.statistics.favorableRate
                    //处方
                    if(it.prescriptionAllow == "1"){
                        tvPrescription.visible()
                    }else{
                        tvPrescription.gone()
                    }
                    //医院三甲
                    if(it.hospitalLevel.isNotEmpty()){
                        tvInspect.visible()
                        tvInspect.text = it.hospitalLevel
                    }else tvInspect.gone()

                    //认证信息
                    if (it.authentication == "1")  {
                        tvDoctorAuth.text = "认证信息：" + it.practiceScope
                        tvDoctorAuthContent.text = "执业证书编号：" + it.certifiedCode

                    }else{
                        tvDoctorAuth.text = "认证信息：无"
                        tvDoctorAuthContent.text = "执业证书编号："
//                        llAuthInfo.gone()
                    }
//                    tvRate.text = it.favorableRate
//                    tvDoctorDept.text = it.departmentName

                    //个人简介、擅长疾病、治疗方案
                    tvDoctorLeftIntro.text = it.introduce
                    tvMeritIllness.text = it.meritIllness
                    tvMeritTherapeutic.text = it.meritTherapeutic

                }
            }
        }

    }

    var tag = "VideoCall:==="
    private  var isMuteAudio = false
    private var isMuteVideo = false
    private  var uid: Long = -100000
    override fun intListener() {
        mBinding.btnAnswerVideo.onClick {
            //自己在频道中对应的uid，大于零有效，无效时服务器会分配随机唯一的uid， 也可以自己生成，但要保证唯一性 这里先写死 加入房间的时候也要用到
            UserInfoManager.getImUserAccount()?.let {
                uid = it.toLong()
            }

            mBinding.videoViewBig.visible()
            videoCallViewModel.acceptInvite(inviteEvent, uid)
            videoCallViewModel.remoteUserJoinChannelLiveData.observe(this) {
                it?.let {

                    NERtcEx.getInstance()
                        .startVideoPreview()//加入房间时，调用 stopVideoPreview(streamType) 方法停止预览
                    NERtcEx.getInstance()
                        .joinChannel(null, it.channelBaseInfo.channelName, uid, null)

                    //接通成功以后
                    mBinding.llDoctorSimpleInfo.gone()
                    mBinding.llDoctorInfo.visible()
                }
            }
        }

        mBinding.btnHangUp.onClick {
            //挂断--拒绝邀请
            videoCallViewModel.rejectInvite(inviteEvent)
            leaveAndClose()
        }

        mBinding.llEnableVideo.onClick {
            //关闭视频
            isMuteVideo = !isMuteVideo
            mBinding.ivMuteVideo.setImageResource(if (isMuteVideo) R.mipmap.video_call_close else R.mipmap.video_call_normal)

            mBinding.btnEnableVideo.text= if (isMuteVideo) "打开视频" else "关闭视频"
            NERtcEx.getInstance().muteLocalVideoStream(isMuteVideo)
            // 切换前后摄像头
//            NERtcEx.getInstance().switchCamera()
        }
        mBinding.llEnableAudio.onClick {
            //关闭音频
            isMuteAudio = !isMuteAudio
            mBinding.ivMuteAudio.setImageResource(
                if (isMuteAudio) R.mipmap.video_audio_close else R.mipmap.video_audio_normal
            )
            mBinding.btnEnableAudio.text= if (isMuteAudio) "打开音频" else "关闭音频"
            NERtcEx.getInstance().muteLocalAudioStream(isMuteAudio)
        }

        //通话结束
        mBinding.llHangUp.onClick {
            //离开频道
            videoCallViewModel.leave(inviteEvent.channelBaseInfo)
            leaveAndClose()
        }
    }


    /**
     * 离开并关闭
     */
    private fun leaveAndClose() {
        innerStop()
        //结束通话
        NERtcEx.getInstance().leaveChannel()
        //释放SDK
        NERtcEx.getInstance().release()
        finish()
    }

    private var player: MediaPlayer = MediaPlayer()
    private fun innerPlay(context:Context) {
        player.run {
            if (isPlaying) {
                stop()
            }
            reset()
            release()
        }
        player = MediaPlayer().apply {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                setAudioAttributes(
                    AudioAttributes.Builder().setLegacyStreamType(AudioManager.STREAM_MUSIC)
                        .build()
                )
            }
            val afd = context.resources.openRawResourceFd(R.raw.avchat_ring)
            if (afd == null) {
                LogUtil.e("can't open resources by ringId")
                return@apply
            }
            try {
                setDataSource(
                    afd.fileDescriptor,
                    afd.startOffset,
                    afd.length
                )
                isLooping = true
                prepare()
                start()
            } catch (e: Exception) {

            }
        }
    }
    private fun innerStop() {
        player.run {
            if (isPlaying) {
                stop()
            }
        }
    }


    override fun onBackPressed() {

        CommonMessageDialog.Builder(this)
            .setTitle("温馨提示")
            .setMessage("是否要结束当前通话?")
            .setConfirm(getStringFromResource(R.string.default_confirm))

            .setCancel(getString(R.string.default_cancel))
            .setonCancelListener {
                it?.dismiss()
            }
            .setonConfirmListener {
                //离开频道
                videoCallViewModel.leave(inviteEvent.channelBaseInfo)
                leaveAndClose()
                it?.dismiss()
                super.onBackPressed()
            }.create().show()

    }

    override fun onDestroy() {
        super.onDestroy()
        innerStop()
        //结束通话
        NERtcEx.getInstance().leaveChannel()
        //释放SDK
        NERtcEx.getInstance().release()
    }

}